我們昨天有提到,在Lex中,若要把檔案印出到terminal,可以使用預定義的參數ECHO
。
Lex除了可以讀取檔案外,也有把讀取的文件印出或輸入到檔案的功能喔!
在這裡我們會用到一個變數yyout
,它跟yyin屬性一樣,是指向 FILE 物件的指標。
透過下面的例子,我們來看看yyout的用法吧!
根據昨天的C++程式碼讀取,我們希望能將非註解的程式碼輸出至txt檔案中。
基本上來說,絕大部分都跟昨天的例子一樣,不同的地方在主程式:
int main(void) {
const char* sFile = "file.cpp";
const char* oFile = "output.cpp";
FILE* fp = fopen(sFile, "r");
if (fp == NULL) {
printf("cannot open %s\n", sFile);
return -1;
}
extern FILE* yyin, *yyout;
yyin = fp;
yyout = fopen(oFile, "w");
yylex();
return 0;
}
在這裡,我們定義yyout
並指定輸出的檔案名稱,再執行檔案的parser。
這裡出現了一個問題:ECHO函式沒有被更改,為什麼輸出路徑就變了呢?
這個問題的答案就藏在編譯過程中生出的lex.yy.c檔案。裡面詳細記錄了轉成C語言的相關函式與變數。我們來看看跟ECHO函式有關的部分
#ifndef ECHO
/* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite().
*/
#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
#endif
看到這裡,我們便可以知道ECHO函式背後的真面目 - 其實就只是C語言的輸出函式而已!
這邊稍微解釋一下新出現的變數 - yyleng
。它是目前讀取到的字串yytext的長度。
因此,我們只要先定義好yyout,就可以決定要把文字輸出到哪裡。
除了ECHO以外,lex檔案中許多變數其實都可以自己更改定義或相關參數,改完後只要到lex.yy.c就可以檢查自己的設定是否正確。
%{
int yylex(void);
%}
%x COMMENT
%%
\/\/ { BEGIN COMMENT; }
<COMMENT>[^\n]* { ; }
<COMMENT>\n { BEGIN 0; ECHO; }
.|\n { ECHO; }
%%
int yywrap(void) {
return 1;
}
int main(void) {
const char* sFile = "file.cpp";
const char* oFile = "output.cpp";
FILE* fp = fopen(sFile, "r");
if (fp == NULL) {
printf("cannot open %s\n", sFile);
return -1;
}
extern FILE* yyin, *yyout;
yyin = fp;
yyout = fopen(oFile, "w");
yylex();
return 0;
}
#include <cstdio>
int main() {
int age = 100; // Input user's age
char* name = "BarleyTea"; // Input user's name
printf("Hi, my name is %s. I am %d years old.\n", name, age); // print user info
}
#include <cstdio>
int main() {
int age = 100;
char* name = "BarleyTea";
printf("Hi, my name is %s. I am %d years old.\n", name, age);
}
透過更改yyout
的方式,可以將文字輸出到指定的外部檔案。
此外,在lex.yy.c檔案中,有多項參數可以自行定義或調整。